
#include <iostream>

# include "Options.hpp"

using namespace Ktracens;

Options::Options() : 
	_description("usage:\tktrace [-aCcdi] [-f trfile] [-g pgrp | -p pid] [-t trstr]\n\tktrace [-adi] [-f trfile] [-t trstr] command")
{
	this->_setDescription();
}

Options::Options(int ac, char** av) : 
	_description("usage:\tktrace [-aCcdi] [-f trfile] [-g pgrp | -p pid] [-t trstr]\n\tktrace [-adi] [-f trfile] [-t trstr] command")
{
	this->_setDescription();
	this->parse(ac, av);
}

Options::~Options()
{

}

bool Options::parse(int ac, char** av)
{
	try
	{
		boost::program_options::store(
			boost::program_options::command_line_parser(ac, av).
		   	options(this->_description).
			positional(this->_positionalDescription).
			run(),
		   	this->_options
		);
		boost::program_options::notify(this->_options);
	} catch (boost::program_options::error const & e) {
		return false;
	}
	return true;
}

bool Options::checkConflicts() const
{
	if (this->exists("command"))
	{
		if (this->exists("pid") || this->exists("gid") || this->exists("C") || this->exists("clear_tracepoints"))
			return true;
	} else {
		if (this->exists("pid") && this->exists("gid"))
			return true;
		if (!(this->exists("pid") || this->exists("gid")))
		 	return true;
	}
	return false;
}

void Options::displayUsage() const
{
	std::cout << this->_description << std::endl;
}

bool Options::exists(std::string const & opt) const
{
	return this->_options.count(opt);
}

void Options::_setDescription()
{
	this->_description.add_options()
		("help,h", "display this help")
		("append,a", "Append to trace file instead of recreating it")
		("C,C", "Disable tracing on user-owned processes (on all processes if user is root) (not handled)")
		("clear_tracepoints,c", "Clear tracepoints associated with the specified files or processes (not handled)")
		("descendant,d", "Perform operation for all current childs of the designated processes (not handled)")
		("outfile,f", boost::program_options::value<std::string>()->default_value("ktrace.out"), "Log trace records to this file")
		("gid,g", boost::program_options::value<int>(), "Enable (disable) tracing on processes in the process group (not handled)")
		("inherit,i", "pass the trace flags to all future children of the designated processes (not handled)")
		("pid,p", boost::program_options::value<int>(), "Enable (disable) tracing on the indicated process id (not handled)")
		("tracepoints,t", boost::program_options::value<std::string>(), 
		 "The string argument represents the kernel trace points, one per letter."
		 " The following table equates the letters with the trace-points:\n\n"
		 "c     trace system calls\n"
		 "i     trace I/O\n"
		 "n     trace namei translations\n"
		 "s     trace signal processing\n"
		 "t     trace various structures\n"
		 "u     userland traces\n"
		 "w     context switches\n"
		 "y     trace sysctl(3) requests\n"
		 "+     trace the default set of trace\n"
	   	 "      points - c, i, n, s, t, u, y\n"
		 "(not handled)")
		("command", boost::program_options::value<std::vector<std::string> >(), "Command to trace (not handled)")
	;
	this->_positionalDescription.add("command", -1);
}

